package com.pilipala.utils;


import com.pilipala.constant.MessageConstant;
import com.pilipala.exception.JwtException;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.security.Key;
import java.util.Date;
import java.util.Map;

@Slf4j
public class JwtUtil {

    /**
     * 生成token
     * @param secretKey 密钥
     * @param ttl 过期时间（毫秒级别）
     * @param claim 放进token的数据
     * @return 加密后的token
     */
    public String generateToken(String secretKey,Long ttl,Map<String,Object> claim){
        SignatureAlgorithm algorithm = SignatureAlgorithm.HS256;

        Key key = Keys.hmacShaKeyFor(secretKey.getBytes()); //获取验证码

        long expTtl = System.currentTimeMillis() + ttl;  //设置过期时间

        return Jwts.builder()
                .setClaims(claim) //设置信息
                .setExpiration(new Date(expTtl)) //设置过期时间
                .signWith(key)  //密钥
                .compact();
    }

    /**
     * 校验token
     * @param secretKey 密钥
     * @param token 前端发送的token
     * @return 返回放在token中的数据
     */
    public Claims parseToken(String secretKey, String token){
        SignatureAlgorithm algorithm = SignatureAlgorithm.HS256;

        Key key = Keys.hmacShaKeyFor(secretKey.getBytes()); //获取验证码

        return Jwts.parserBuilder()
                .setSigningKey(key)
                .build()
                .parseClaimsJws(token).getBody();
    }

    /**
     * 判断token是否合法
     * 判断token是否过期
     * @param secretKey 密钥
     * @param token token
     * @return 是否合法？
     */
    public boolean validateToken(String secretKey,String token){
        Claims claims;
        try{
            claims = parseToken(secretKey, token);
        }
        catch(ExpiredJwtException exception){
//            解析失败
            throw new JwtException(MessageConstant.TOKEN_OUT_OF_TIME);
        }
//        获取过期时间
        Date date = claims.getExpiration();
        return !date.before(new Date());
    }
}
